﻿
using GrainManage.Core.Access.Interfaces;
using GrainManage.Core.Provider.Interfaces;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Text.RegularExpressions;

namespace GrainManage.Core.Access
{
    public class CachedParameterBuilder : IParameterBuilder
    {
        private static Dictionary<string, string[]> CachedParameters = new Dictionary<string, string[]>();

        private static object lockObj = new object();

        private IProvider Provider;

        public CachedParameterBuilder(IProvider provider)
        {
            this.Provider = provider;
        }

        public void AddParameters(DbCommand cmd, object[] parameterValues)
        {
            var procName = cmd.CommandText;
            if (!CachedParameters.ContainsKey(procName))
            {
                string fullParas = null;
                using (var con = Provider.Connection)
                {
                    var scmd = Provider.GetCommand("ProcInfo_GetParaByName", con);
                    scmd.Parameters.Add(Provider.GetDbParameter("xProcName", procName));
                    scmd.Parameters.Add(Provider.GetDbParameter("xCanWriteBack", false));
                    if (con.State == ConnectionState.Closed) { con.Open(); }
                    fullParas = scmd.ExecuteScalar() as string;
                    fullParas = string.IsNullOrEmpty(fullParas) ? string.Empty : fullParas.Trim(' ');
                }

                string[] splitParameters = new string[0];
                if (fullParas.Length > 0)
                {
                    fullParas = Regex.Replace(fullParas, @"\([\s,\d]*\)", string.Empty);//去除形如'(xx)'的字符串
                    fullParas = Regex.Replace(fullParas, @"[\s]*\,[\s]*", ",");//去除','前后的空白
                    splitParameters = fullParas.Split(',');
                    for (int i = 0; i < splitParameters.Length; i++)
                    {
                        splitParameters[i] = splitParameters[i].Split(' ')[0];
                    }
                }

                lock (lockObj)
                {
                    if (!CachedParameters.ContainsKey(procName))
                    {
                        CachedParameters[procName] = splitParameters;
                    }
                }
            }

            var parameterNames = CachedParameters[procName];
            if (parameterNames.Length != parameterValues.Length)
            {
                throw new System.Exception("the number of parameters is not right.");
            }

            for (int i = 0; i < parameterNames.Length; i++)
            {
                cmd.Parameters.Add(Provider.GetDbParameter(parameterNames[i], parameterValues[i]));
            }
        }
    }
}
